1   /*
2    * Copyright (C) 2013 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5    * in compliance with the License. You may obtain a copy of the License at
6    *
7    * http://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software distributed under the License
10   * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11   * or implied. See the License for the specific language governing permissions and limitations under
12   * the License.
13   */
14  
15  package com.google.common.collect;
16  
17  import static com.google.common.base.Preconditions.checkNotNull;
18  
19  import com.google.common.annotations.GwtCompatible;
20  import com.google.common.base.Objects;
21  import com.google.common.base.Predicate;
22  import com.google.common.base.Predicates;
23  
24  import java.util.AbstractCollection;
25  import java.util.Collection;
26  import java.util.Iterator;
27  import java.util.Map;
28  import java.util.Map.Entry;
29  
30  import javax.annotation.Nullable;
31  
32  /**
33   * Implementation for {@link FilteredMultimap#values()}.
34   * 
35   * @author Louis Wasserman
36   */
37  @GwtCompatible
38  final class FilteredMultimapValues<K, V> extends AbstractCollection<V> {
39    private final FilteredMultimap<K, V> multimap;
40  
41    FilteredMultimapValues(FilteredMultimap<K, V> multimap) {
42      this.multimap = checkNotNull(multimap);
43    }
44  
45    @Override
46    public Iterator<V> iterator() {
47      return Maps.valueIterator(multimap.entries().iterator());
48    }
49  
50    @Override
51    public boolean contains(@Nullable Object o) {
52      return multimap.containsValue(o);
53    }
54  
55    @Override
56    public int size() {
57      return multimap.size();
58    }
59  
60    @Override
61    public boolean remove(@Nullable Object o) {
62      Predicate<? super Entry<K, V>> entryPredicate = multimap.entryPredicate();
63      for (Iterator<Entry<K, V>> unfilteredItr = multimap.unfiltered().entries().iterator();
64          unfilteredItr.hasNext();) {
65        Map.Entry<K, V> entry = unfilteredItr.next();
66        if (entryPredicate.apply(entry) && Objects.equal(entry.getValue(), o)) {
67          unfilteredItr.remove();
68          return true;
69        }
70      }
71      return false;
72    }
73  
74    @Override
75    public boolean removeAll(Collection<?> c) {
76      return Iterables.removeIf(multimap.unfiltered().entries(),
77          // explicit <Entry<K, V>> is required to build with JDK6
78          Predicates.<Entry<K, V>>and(multimap.entryPredicate(),
79              Maps.<V>valuePredicateOnEntries(Predicates.in(c))));
80    }
81  
82    @Override
83    public boolean retainAll(Collection<?> c) {
84      return Iterables.removeIf(multimap.unfiltered().entries(),
85          // explicit <Entry<K, V>> is required to build with JDK6
86          Predicates.<Entry<K, V>>and(multimap.entryPredicate(),
87              Maps.<V>valuePredicateOnEntries(Predicates.not(Predicates.in(c)))));
88    }
89  
90    @Override
91    public void clear() {
92      multimap.clear();
93    }
94  }